﻿using System;
using System.Configuration;
using System.IO;
using System.Text;

using Microsoft.SharePoint;

namespace Eneta.Portal.Common.Loggers
{
    /// <summary>
    /// <see cref="ILogger"/> implementation that uses custom output file.
    /// </summary>
    public class FileLogger : ILogger
    {
        private readonly string _path;

        /// <summary>
        /// Initializes a new instance of the <see cref="FileLogger"/> class.
        /// </summary>
        public FileLogger() : this(ConfigurationManager.AppSettings["FileLogger.Path"])
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="FileLogger"/> class.
        /// </summary>
        /// <param name="logPath">The path to log file.</param>
        public FileLogger(string logPath)
        {
            var file = new FileInfo(logPath);
            if(file.Directory == null )
                throw new FileNotFoundException("Cannot find log file " + logPath);
            if(!file.Directory.Exists)
                throw new FileNotFoundException("Cannot find log file " + file.Directory.FullName);
            _path = logPath;
        }

        /// <summary>
        /// Writes the informative message to log.
        /// </summary>
        /// <param name="message">The message to log.</param>
        /// <param name="source">The source of message.</param>
        public void LogInfo(string message, string source)
        {
            SaveMessage(message);
        }

        /// <summary>
        /// Writes the warning message to log.
        /// </summary>
        /// <param name="message">The message to log.</param>
        /// <param name="source">The source of message.</param>
        public void LogWarning(string message, string source)
        {
            SaveMessage(message);
        }

        /// <summary>
        /// Logs the exception.
        /// </summary>
        /// <param name="ex">The exception to log.</param>
        public void LogException(Exception ex)
        {
            var output = new StringBuilder();
            while(ex != null)
            {
                output.AppendLine(ex.ToString());
                ex = ex.InnerException;
            }

            SaveMessage(output.ToString());
        }

        /// <summary>
        /// Saves the message to log file.
        /// </summary>
        /// <param name="message">The message to be saved.</param>
        private void SaveMessage(string message)
        {
            var sec = new SPSecurity.CodeToRunElevated(
                delegate
                    {
                        using (var stream = File.OpenWrite(_path))
                        {
                            stream.Seek(0, SeekOrigin.End);
                            using (var writer = new StreamWriter(stream))
                            {
                                writer.Write(DateTime.Now.ToString());
                                writer.Write(" ");
                                writer.WriteLine(message);
                                writer.Flush();
                            }
                        }
                    });
            SPSecurity.RunWithElevatedPrivileges(sec);
        }
    }
}
